package com.example.rxohosaudio.ability;

import com.example.rxharmonyaudio.PlayConfig;
import com.example.rxharmonyaudio.RxAudioPlayer;
import com.example.rxohosaudio.AudioRecorder;
import io.reactivex.Scheduler;
import io.reactivex.functions.Action;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.internal.functions.Functions;
import io.reactivex.plugins.RxJavaPlugins;
import io.reactivex.schedulers.Schedulers;
import ohos.media.audio.AudioManager;
import ohos.media.common.AudioProperty;
import ohos.media.common.Source;
import ohos.media.common.StorageProperty;
import ohos.media.recorder.Recorder;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.io.File;
import java.util.LinkedList;
import java.util.Queue;

public class FileAbilityOhosTest {

    private static final int AUDIO_SAMPLE_RATE_HZ = 8000;
    private static final int AUDIO_BIT_RATE_HZ = 192000;

    @Test
    public void startAudioRecorderAfterPrepareRecord() {
        AudioRecorder mAudioRecorder = AudioRecorder.getInstance();

        File mAudioFile = new File("data/data/com.example.rxohosaudio/"
                + File.separator + System.nanoTime() + ".mp4");

        Source source = new Source();
        source.setRecorderAudioSource(Recorder.AudioSource.MIC);

        AudioProperty audioProperty = new AudioProperty.Builder()
                .setRecorderSamplingRate(AUDIO_SAMPLE_RATE_HZ)
                .setRecorderBitRate(AUDIO_BIT_RATE_HZ)
                .setRecorderAudioEncoder(Recorder.AudioEncoder.AAC)
                .build();
        StorageProperty storageProperty = new StorageProperty.Builder()
                .setRecorderFile(mAudioFile)
                .setRecorderMaxDurationMs(-1)
                .setRecorderMaxFileSizeBytes(-1)
                .build();

        mAudioRecorder.prepareRecord(source, Recorder.OutputFormat.MPEG_4,
                audioProperty, storageProperty);

        boolean isStart = mAudioRecorder.startRecord();

        Assert.assertTrue(isStart);
    }

    @Test
    public void startAudioRecorderWithoutPrepare() {
        AudioRecorder mAudioRecorder = AudioRecorder.getInstance();
        boolean isStart = mAudioRecorder.startRecord();

        Assert.assertFalse(isStart);
    }

    @Test
    public void stopRecorder() {
        AudioRecorder mAudioRecorder = AudioRecorder.getInstance();
        File mAudioFile = new File("data/data/com.example.rxohosaudio/"
                + File.separator + System.nanoTime() + ".mp4");

        Source source = new Source();
        source.setRecorderAudioSource(Recorder.AudioSource.MIC);

        AudioProperty audioProperty = new AudioProperty.Builder()
                .setRecorderSamplingRate(AUDIO_SAMPLE_RATE_HZ)
                .setRecorderBitRate(AUDIO_BIT_RATE_HZ)
                .setRecorderAudioEncoder(Recorder.AudioEncoder.AAC)
                .build();
        StorageProperty storageProperty = new StorageProperty.Builder()
                .setRecorderFile(mAudioFile)
                .setRecorderMaxDurationMs(-1)
                .setRecorderMaxFileSizeBytes(-1)
                .build();

        mAudioRecorder.prepareRecord(source, Recorder.OutputFormat.MPEG_4,
                audioProperty, storageProperty);

        boolean isStart = mAudioRecorder.startRecord();

        Assert.assertTrue(isStart);

        mAudioRecorder.stopRecord();

        Assert.assertFalse(mAudioRecorder.isStarted());
    }

    @Test
    public void stopRecorderGetLength() {
        AudioRecorder mAudioRecorder = AudioRecorder.getInstance();
        File mAudioFile = new File("data/data/com.example.rxohosaudio/"
                + File.separator + System.nanoTime() + ".mp4");

        Source source = new Source();
        source.setRecorderAudioSource(Recorder.AudioSource.MIC);

        AudioProperty audioProperty = new AudioProperty.Builder()
                .setRecorderSamplingRate(AUDIO_SAMPLE_RATE_HZ)
                .setRecorderBitRate(AUDIO_BIT_RATE_HZ)
                .setRecorderAudioEncoder(Recorder.AudioEncoder.AAC)
                .build();
        StorageProperty storageProperty = new StorageProperty.Builder()
                .setRecorderFile(mAudioFile)
                .setRecorderMaxDurationMs(-1)
                .setRecorderMaxFileSizeBytes(-1)
                .build();

        mAudioRecorder.prepareRecord(source, Recorder.OutputFormat.MPEG_4,
                audioProperty, storageProperty);

        boolean isStart = mAudioRecorder.startRecord();

        Assert.assertTrue(isStart);

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        int length = mAudioRecorder.stopRecord();

        Assert.assertEquals(length, 5);
    }

//    private static final int AUDIO_SAMPLE_RATE_HZ = 8000;
//    private static final int AUDIO_BIT_RATE_HZ = 192000;
    private File mAudioFile;

    /**
     * 单元测试的时候，利用RxJavaPlugins将io线程转换为trampoline
     */
    public static void asyncToSync() {
        RxJavaPlugins.reset();
        RxJavaPlugins.setIoSchedulerHandler(new Function<Scheduler, Scheduler>() {
            @Override
            public Scheduler apply(Scheduler scheduler) throws Exception {
                return Schedulers.trampoline();
            }
        });
    }

    @Before
    public void setUp(){
        //将rx异步转同步
        asyncToSync();
        startRecorder();
    }

    public void startRecorder() {
        AudioRecorder mAudioRecorder = AudioRecorder.getInstance();
        mAudioFile = new File("data/data/com.example.rxohosaudio/"
                + File.separator + System.nanoTime() + ".mp4");

        Source source = new Source();
        source.setRecorderAudioSource(Recorder.AudioSource.MIC);

        AudioProperty audioProperty = new AudioProperty.Builder()
                .setRecorderSamplingRate(AUDIO_SAMPLE_RATE_HZ)
                .setRecorderBitRate(AUDIO_BIT_RATE_HZ)
                .setRecorderAudioEncoder(Recorder.AudioEncoder.AAC)
                .build();
        StorageProperty storageProperty = new StorageProperty.Builder()
                .setRecorderFile(mAudioFile)
                .setRecorderMaxDurationMs(-1)
                .setRecorderMaxFileSizeBytes(-1)
                .build();

        mAudioRecorder.prepareRecord(source, Recorder.OutputFormat.MPEG_4,
                audioProperty, storageProperty);

        mAudioRecorder.stopRecord();
    }

//    @Test
//    public void rxAudioPlayerGetMediaPlayerWithoutCreate() {
//
//        RxAudioPlayer mRxAudioPlayer = RxAudioPlayer.getInstance();
//        Player mediaPlayer = mRxAudioPlayer.getMediaPlayer();
//        Assert.assertNull(mediaPlayer);
//    }

    @Test
    public void rxAudioPlayerPlay() {
        RxAudioPlayer mRxAudioPlayer = RxAudioPlayer.getInstance();

        boolean[] playSuccess = {false};

        PlayConfig playConfig = PlayConfig.file(mAudioFile)
                .streamType(AudioManager.AudioVolumeType.STREAM_VOICE_CALL)
                .build();

        mRxAudioPlayer.play(playConfig)
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .subscribe(new Consumer<Boolean>() {
                    @Override
                    public void accept(Boolean aBoolean) throws Exception {
                        playSuccess[0] = aBoolean;
                        System.out.println("--> play success : " + aBoolean);
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        System.out.println("--> throwable : " + throwable.getMessage());
                    }
                });

        Assert.assertTrue(playSuccess[0]);
    }

    @Test
    public void rxAudioPlayerPlayWithNullFile() {
        RxAudioPlayer mRxAudioPlayer = RxAudioPlayer.getInstance();

        Queue<File> mAudioFiles = new LinkedList<>();
        File audioFile = mAudioFiles.poll();

        boolean[] throwError = {false};

        PlayConfig playConfig = PlayConfig.file(audioFile)
                .streamType(AudioManager.AudioVolumeType.STREAM_VOICE_CALL)
                .build();

        mRxAudioPlayer.play(playConfig)
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .subscribe(Functions.emptyConsumer(), new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        throwError[0] = true;
                    }
                }, new Action() {
                    @Override
                    public void run() throws Exception {

                    }
                });

        Assert.assertTrue(throwError[0]);
    }

    @Test
    public void rxAudioPlayerPrepare() {
        RxAudioPlayer mRxAudioPlayer = RxAudioPlayer.getInstance();

        PlayConfig playConfig = PlayConfig.file(mAudioFile)
                .streamType(AudioManager.AudioVolumeType.STREAM_VOICE_CALL)
                .build();

        final boolean[] playSuccess = {false};

        mRxAudioPlayer.prepare(playConfig)
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .subscribe(new Consumer<Boolean>() {
                    @Override
                    public void accept(Boolean aBoolean) throws Exception {
                        playSuccess[0] = aBoolean;
                    }
                });

        Assert.assertTrue(playSuccess[0]);
    }

    @Test
    public void rxAudioPlayerPrepareWithNullFile() {
        RxAudioPlayer mRxAudioPlayer = RxAudioPlayer.getInstance();

        Queue<File> mAudioFiles = new LinkedList<>();
        File audioFile = mAudioFiles.poll();

        PlayConfig playConfig = PlayConfig.file(audioFile)
                .streamType(AudioManager.AudioVolumeType.STREAM_VOICE_CALL)
                .build();

        final boolean[] throwError = {false};

        mRxAudioPlayer.prepare(playConfig)
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .subscribe(new Consumer<Boolean>() {
                    @Override
                    public void accept(Boolean aBoolean) throws Exception {
                        System.out.println("--> next boolean : " + aBoolean);
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        System.out.println("--> throwable : " + throwable.getMessage());
                        throwError[0] = true;
                    }
                }, new Action() {
                    @Override
                    public void run() throws Exception {
                        System.out.println("--> action finish!!");
                    }
                });

        Assert.assertTrue(throwError[0]);
    }
}